﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Web;
using System.IO;
using System.Collections;
//using System.Web.Script.Serialization;

namespace Artix
{
    public enum ChartType
    {
        line,
        area,
        pie,
        area3d,
        bar,
        bubble
    }

    public enum KeyType
    {
        Date = 0,
        String = 1
    }

    public enum AnimationEffect
    {
        Default = 0,
        StretchVertical = 1,
        StretchHorizontal = 2,
        SlideDown = 3,
        SlideUp = 4,
        SlideRight = 5,
        SlideLeft = 6
    }

    public enum MarkerType
    {
        circle = 0,
        diamond = 1
    }

    [DataContract]
    public class Preview
    {
        private bool _visible = false;
        [DataMember(Name = "visible", Order = 1)]
        public bool Visible
        { get { return _visible; } set { _visible = value; } }

        private int _height;
        [DataMember(Name = "height", Order = 2, EmitDefaultValue = false)]
        public int Height
        { get { return _height; } set { _height = value; } }
    }

    [DataContract]
    public class Legend
    {
        private string _layout;
        [DataMember(Name = "layout", Order = 0, EmitDefaultValue = false)]
        public string Layout
        { get { return _layout; } set { _layout = value; } }
        
        private string _position;
        /// <summary>
        /// Format "left top"?
        /// </summary>
        [DataMember(Name = "position", Order = 1, EmitDefaultValue = false)]
        public string Position
        { get { return _position; } set { _position = value; } }

        private int _alpha = 1;
        [DataMember(Name = "alpha", Order = 2)]
        public int Alpha
        { get { return _alpha; } set { _alpha = value; } }

        private int _borderWidth = 0;
        [DataMember(Name = "border-width", Order = 3)]
        public int BorderWidth
        { get { return _borderWidth; } set { _borderWidth = value; } }

        /*
            "margin-bottom":15,
            "layout":"horizontal",
            "width":250,
            "border-width":0,
            "alpha":0.5,
            "background-color":-1,
            "shadow":false,
            "margin-left":20,
            "item":{
                "font-color":"#ececd4",
                "border-width":0,
                "bold":true
        */
    }

    [DataContract]
    public class Marker
    {
        private MarkerType _type = MarkerType.circle;
        [DataMember(Name = "type", Order = 1, EmitDefaultValue = false)]
        public string Type
        { get { return _type.ToString(); } set { value = value; } } // Apparently serialization isn't allowed for read-only properties. Thus value=value

        private int _size;
        [DataMember(Name = "size", Order = 2, EmitDefaultValue = false)]
        public int Size
        { get { return _size; } set { _size = value; } }

        private string _backgroundColor;
        [DataMember(Name = "background-color", Order = 3, EmitDefaultValue = false)]
        public string BackgroundColor
        { get { return _backgroundColor; } set { _backgroundColor = value; } }

        private string _backgroundColor2;
        [DataMember(Name = "background-color-2", Order = 4, EmitDefaultValue = false)]
        public string BackgroundColor2
        { get { return _backgroundColor2; } set { _backgroundColor2 = value; } }

        private decimal _alpha;
        [DataMember(Name = "alpha", Order = 5, EmitDefaultValue = false)]
        public decimal Alpha
        { get { return _alpha; } set { _alpha = value; } }
    }

    [DataContract]
    public class Title
    {
        private string _text;
        [DataMember(Name = "text", Order = 1, EmitDefaultValue = false)]
        public string Text
        { get { return _text; } set { _text = value; } }

        private string _backgroundColor;
        [DataMember(Name = "background-color", Order = 2, EmitDefaultValue = false)]
        public string BackgroundColor
        { get { return _backgroundColor; } set { _backgroundColor = value; } }

        private string _fontColor;
        [DataMember(Name = "font-color", Order = 3, EmitDefaultValue = false)]
        public string FontColor
        { get { return _fontColor; } set { _fontColor = value; } }
    }

    [DataContract]
    public class Plot
    {
        private string _tooltipText;
        [DataMember(Name = "tooltipText", Order = 1, EmitDefaultValue = false)]
        public string TooltipText
        { get { return _tooltipText; } set { _tooltipText = value; } }

        private bool _highlight;
        [DataMember(Name = "highlight", Order = 2, EmitDefaultValue = false)]
        public bool Highlight
        { get { return _highlight; } set { _highlight = value; } }

        private bool _animate;
        [DataMember(Name = "animate", Order = 3, EmitDefaultValue = false)]
        public bool Animate
        { get { return _animate; } set { _animate = value; } }

        private AnimationEffect _animationEffect;
        [DataMember(Name = "effect", Order = 4, EmitDefaultValue = false)]
        public AnimationEffect AnimationEffect
        { get { return _animationEffect; } set { _animationEffect = value; } }

        private decimal _animationSpeed;
        [DataMember(Name = "speed", Order = 5, EmitDefaultValue = false)]
        public decimal AnimationSpeed
        { get { return _animationSpeed; } set { _animationSpeed = value; } }

        private decimal _alphaArea;
        [DataMember(Name = "alpha-area", Order = 6, EmitDefaultValue = false)]
        public decimal AlphaArea
        { get { return _alphaArea; } set { _alphaArea = value; } }

    }

    [DataContract]
    public class PlotArea
    {
        private string _width;
        [DataMember(Name = "width", Order = 1, EmitDefaultValue = false)]
        public string Width
        { get { return _width; } set { _width = value; } }

        private string _height;
        [DataMember(Name = "height", Order = 2, EmitDefaultValue = false)]
        public string Height
        { get { return _height; } set { _height = value; } }

        private string _position;
        [DataMember(Name = "position", Order = 3, EmitDefaultValue = false)]
        public string Position
        { get { return _position; } set { _position = value; } }

        private string _margin;
        [DataMember(Name = "margin", Order = 4, EmitDefaultValue = false)]
        public string Margin
        { get { return _margin; } set { _margin = value; } }

        private string _backgroundColor;
        [DataMember(Name = "background-color", Order = 5, EmitDefaultValue = false)]
        public string BackgroundColor
        { get { return _backgroundColor; } set { _backgroundColor = value; } }

        private string _marginTop;
        [DataMember(Name = "margin-top", Order = 6, EmitDefaultValue = false)]
        public string MarginTop
        { get { return _marginTop; } set { _marginTop = value; } }

        private string _marginRight;
        [DataMember(Name = "margin-right", Order = 7, EmitDefaultValue = false)]
        public string MarginRight
        { get { return _marginRight; } set { _marginRight = value; } }

        private string _marginLeft;
        [DataMember(Name = "margin-left", Order = 8, EmitDefaultValue = false)]
        public string MarginLeft
        { get { return _marginLeft; } set { _marginLeft = value; } }

        private string _marginBottom;
        [DataMember(Name = "margin-bottom", Order = 9, EmitDefaultValue = false)]
        public string MarginBottom
        { get { return _marginBottom; } set { _marginBottom = value; } }
    }

    [DataContract]
    public class Guide
    {
        private bool _visible;
        [DataMember(Name = "visible", Order = 1, EmitDefaultValue = false)]
        public bool Visible
        { get { return _visible; } set { _visible = value; } }

        private string _height;
        [DataMember(Name = "height", Order = 2, EmitDefaultValue = false)]
        public string Height
        { get { return _height; } set { _height = value; } }

        private string _tooltipText = "%v";
        [DataMember(Name = "tooltip-text", Order = 3, EmitDefaultValue = false)]
        public string TooltipText
        { get { return _tooltipText; } set { _tooltipText = value; } }

        private string _lineColor;
        [DataMember(Name = "line-color", Order = 4, EmitDefaultValue = false)]
        public string LineColor
        { get { return _lineColor; } set { _lineColor = value; } }

        private int _lineWidth;
        [DataMember(Name = "line-width", Order = 5, EmitDefaultValue = false)]
        public int LineWidth
        { get { return _lineWidth; } set { _lineWidth = value; } }
    }

    [DataContract]
    public class Lens
    {
        private bool _visible;
        [DataMember(Name = "visible", Order = 1, EmitDefaultValue = false)]
        public bool Visible
        { get { return _visible; } set { _visible = value; } }

        private string _height;
        [DataMember(Name = "height", Order = 2, EmitDefaultValue = false)]
        public string Height
        { get { return _height; } set { _height = value; } }

        private string _width;
        [DataMember(Name = "width", Order = 2, EmitDefaultValue = false)]
        public string Width
        { get { return _width; } set { _width = value; } }

    }

    [DataContract]
    public class Series
    {
        public Series() { }

        public Series(string label, ChartType chartType)
        {
            if (chartType != ChartType.pie)
                _marker = new Artix.Marker();
            _label = label;
        }

        private string _backgroundColor;
        [DataMember(Name = "background-color", Order = 2, EmitDefaultValue = false)]
        public string BackgroundColor
        { get { return _backgroundColor; } set { _backgroundColor = value; } }

        private string _label;
        [DataMember(Name = "text", Order = 3)]
        public string Label
        { get { return _label; } set { _label = value; } }

        private string _lineColor;
        [DataMember(Name = "line-color", Order = 4, EmitDefaultValue = false)]
        public string LineColor
        { get { return _lineColor; } set { _lineColor = value; } }

        private int _lineWidth = 2;
        [DataMember(Name = "line-width", Order = 5)]
        public int LineWidth
        { get { return _lineWidth; } set { _lineWidth = value; } }

        private Marker _marker;
        [DataMember(Name = "marker", Order = 6, EmitDefaultValue = false)]
        public Marker Marker
        { get { return _marker; } set { _marker = value; } }

        private decimal[] _values;
        [DataMember(Name = "values", Order = 7, EmitDefaultValue = true)]
        public decimal[] Values
        { get { return _values; } set { _values = value; } }

        private bool _shadow;
        [DataMember(Name = "shadow", Order = 8)]
        public bool Shadow
        { get { return _shadow; } set { _shadow = value; } }
    }

    [DataContract]
    public class YScale
    {
        private decimal _min;
        [DataMember(Name = "min", Order = 0, EmitDefaultValue = false)]
        public decimal Min
        { get { return _min; } set { _min = value; } }

        private decimal _max;
        [DataMember(Name = "max", Order = 1, EmitDefaultValue = false)]
        public decimal Max
        { get { return _max; } set { _max = value; } }

        private string _format;
        [DataMember(Name = "format", Order = 2, EmitDefaultValue = false)]
        public string Format
        { get { return _format; } set { _format = value; } }

        private string _thousandsSeparator;
        [DataMember(Name = "thousands-separator", Order = 3, EmitDefaultValue = false)]
        public string ThousandsSeparator
        { get { return _thousandsSeparator; } set { _thousandsSeparator = value; } }

        private int _maxLabels;
        [DataMember(Name = "max-labels", Order = 4, EmitDefaultValue = false)]
        public int MaxLabels
        { get { return _maxLabels; } set { _maxLabels = value; } }

    }

    [DataContract]
    public class XScale
    {
        private string _format;
        [DataMember(Name = "format", Order = 0, EmitDefaultValue = false)]
        public string Format
        { get { return _format; } set { _format = value; } }

        private object[] _values;
        [DataMember(Name = "values", EmitDefaultValue = false)]
        public object[] Values
        { get { return _values; } set { _values = value; } }
    }

    [DataContract]
    public class ZingChart
    {
        public ZingChart(ChartType type)
        {
            _type = type;
        }

        public ZingChart(ChartType type, string title, bool preview)
        {
            _type = type;
            _title = new Artix.Title();
            _title.Text = title;
            _preview = new Artix.Preview();
            _preview.Visible = preview;
        }

        private string _BackgroundColor;
        [DataMember(Name = "background-color", Order = 0, EmitDefaultValue = false)]
        public string BackgroundColor
        {
            get { return _BackgroundColor; }
            set { _BackgroundColor = value; }
        }

        private string _BackgroundColor2;
        [DataMember(Name = "background-color-2", Order = 0, EmitDefaultValue = false)]
        public string BackgroundColor2
        {
            get { return _BackgroundColor2; }
            set { _BackgroundColor2 = value; }
        }

        private Title _title;
        [DataMember(Name = "title", Order = 1, EmitDefaultValue = false)]
        public Title Title
        { 
            get 
            { return _title; } 
            set { _title = value; } 
        }

        private Preview _preview;
        [DataMember(Name = "preview", Order = 2, EmitDefaultValue = false)]
        public Preview Preview
        { get { return _preview; } set { _preview = value; } }

        private ChartType _type;
        [DataMember(Name = "type", Order = 3)]
        public string Type
        { get { return _type.ToString(); } set { value = value; } } // Apparently serialization isn't allowed for read-only properties. Thus value=value

        private bool _stacked = false;
        [DataMember(Name = "stacked", Order = 4, EmitDefaultValue = false)]
        public bool Stacked
        { get { return _stacked; } set { _stacked = value; } }

        private XScale _xScale;
        [DataMember(Name = "scale-x", Order = 5)]
        public XScale XScale
        { get { return _xScale; } set { _xScale = value; } }

        private YScale _yScale;
        [DataMember(Name = "scale-y", Order = 6, EmitDefaultValue = false)]
        public YScale YScale
        { get { return _yScale; } set { _yScale = value; } }

        private Plot _plot;
        [DataMember(Name = "plot", Order = 7, EmitDefaultValue = false)]
        public Plot Plot
        { get { return _plot; } set { _plot = value; } }

        private PlotArea _plotArea;
        [DataMember(Name = "plotarea", Order = 8, EmitDefaultValue = false)]
        public PlotArea PlotArea
        { get { return _plotArea; } set { _plotArea = value; } }

        private Guide _guide;
        [DataMember(Name = "guide", Order = 9, EmitDefaultValue = false)]
        public Guide Guide
        { get { return _guide; } set { _guide = value; } }

        private Lens _lens;
        [DataMember(Name = "lens", Order = 10, EmitDefaultValue = false)]
        public Lens Lens
        { get { return _lens; } set { _lens = value; } }

        private Legend _legend;
        [DataMember(Name = "legend", Order = 10)]
        public Legend Legend
        { 
            get { return _legend; } 
            set { _legend = value; } 
        }

        private List<Series> _series = new List<Series>();
        [DataMember(Name = "series", Order = 11)]
        public List<Series> Series
        { get { return _series; } set { _series = value; } }

        /// <summary>
        /// Adds type/value pairs to be serialized later.
        /// </summary>
        /// <param name="typeValuePair">Dictionary</param>
        /// <param name="keyType">Data type of dictionary object.</param>
        /// <param name="xScaleFormat">Format for dictionary object. Ex. "MM-d-yyyy" for a date.</param>
        /// <param name="legendLabel">The label for the chart legend.</param>
        /// <param name="series">Optional index of an existing series.</param>
        public void AddTypeValuePair(Dictionary<object, decimal> typeValuePair, KeyType keyType, string xScaleFormat, string legendLabel)
        {
            if (_type == ChartType.pie)
            {
                int pairs = typeValuePair.Count();

                for (int i = 0; i < pairs; i++)
                {
                    _series.Add(new Series(typeValuePair.ElementAt(i).Key.ToString(), _type));
                    int series = _series.Count - 1;
                    _series[series].Values = new decimal[1];
                    _series[series].Values[0] = typeValuePair.ElementAt(i).Value;
                }
            }
            else
            {
                bool newTypes = true;
                // If the scale labels have already been 
                // populated, don't save them again
                if (_xScale != null) newTypes = false;

                int pairs = typeValuePair.Count();
                if (newTypes)
                {
                    _xScale = new XScale();
                    _xScale.Values = new object[pairs];
                }

                _series.Add(new Series(legendLabel, _type));

                int series = _series.Count - 1;
                _series[series].Values = new decimal[pairs];

                for (int i = 0; i < pairs; i++)
                {
                    if (newTypes)
                    {
                        if (keyType == KeyType.Date)
                        {
                            _xScale.Values[i] = ((DateTime)typeValuePair.ElementAt(i).Key).ToString(xScaleFormat);
                        }
                        else if (keyType == KeyType.String)
                        {
                            _xScale.Values[i] = typeValuePair.ElementAt(i).Key.ToString();
                        }
                    }

                    _series[series].Values[i] = typeValuePair.ElementAt(i).Value;
                }
            }
        }

        public string ValuesToJSON()
        {
            System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(this.Series.GetType());
            MemoryStream ms = new MemoryStream();
            serializer.WriteObject(ms, this.Series);
            string json = Encoding.Default.GetString(ms.ToArray());
            return json;
        }

        public string ToJSON()
        { 
            System.Runtime.Serialization.Json.DataContractJsonSerializer serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(this.GetType());
            MemoryStream ms = new MemoryStream();
            serializer.WriteObject(ms, this);
            string json = Encoding.Default.GetString(ms.ToArray());
            return json;
        }
    }

}
